package gis

import (
	"bytes"
	"dgo/goutils/utils"
)

type NmeaDecoder struct {
	decodeState  int
	starIdx      int // 星号的索引
	cache        utils.BytesBuilder
	LastNmeaText string
	OnNmea       func(sender *NmeaDecoder, nmea string)
}

func CheckIsNmea(data []byte) bool {
	if bytes.Index(data, []byte("$GP")) > -1 {
		return true
	}

	if bytes.Index(data, []byte("$GN")) > -1 {
		return true
	}

	if bytes.Index(data, []byte("$command")) > -1 {
		return true
	}
	return false
}

func CheckIsGGA(data []byte) bool {
	if bytes.Index(data, []byte("GGA")) > -1 {
		return true
	}
	return false
}

func NewNmeaDecoder() *NmeaDecoder {
	rval := &NmeaDecoder{}
	return rval
}

func (this *NmeaDecoder) Reset() {
	this.cache.Reset()
	this.decodeState = 1
	this.starIdx = 0
}

func (this *NmeaDecoder) InputText(txt string) {
	this.InputBuf([]byte(txt))
}

func (this *NmeaDecoder) InputBuf(buf []byte) int {
	rval := 0
	for i := 0; i < len(buf); i++ {
		if this.InputByte(buf[i]) == 1 {
			rval++
		}
	}
	return rval
}

func (this *NmeaDecoder) GetNMEAText() string {
	return this.cache.String()
}

/*
*

	如果不合法,去掉不合理的地方
*/
func (this *NmeaDecoder) checkRepair() {
	if this.cache.Byte(0) == '$' && this.cache.Byte(1) == '$' { // 头部双多个$$
		if this.CheckValid() { // 只使用标志方式检测
			return
		}

		for {
			if this.cache.Byte(0) == '$' && this.cache.Byte(1) == '$' {
				this.cache.Delete(0, 1)
			} else {
				break
			}
		}
	}
}

/*
*
直接去掉不合理的地方
*/
func (this *NmeaDecoder) Repair() {
	for {
		if this.cache.Byte(0) == '$' && this.cache.Byte(1) == '$' {
			this.cache.Delete(0, 1)
		} else {
			break
		}
	}
}

func (this *NmeaDecoder) CheckIsGGA() bool {
	return this.cache.Index(0, []byte("GGA")) > -1
}

func (this *NmeaDecoder) CheckValid() bool {
	str := this.cache.String()
	if str[0] != '$' {
		return false
	}
	if len(str) < 4 {
		return false
	}
	crc0 := str[len(str)-2:]
	str = str[1 : len(str)-3]
	crc := CRC([]byte(str))
	v := utils.HexToInt(crc0)
	r := crc == byte(v)
	return r
}

/*
*

	$command,log COM2 rtcm1127 ontime 1,response: OK*61
*/
func (this *NmeaDecoder) CheckValid2() bool {
	str := this.cache.String()
	if str[0] != '$' {
		return false
	}
	if len(str) < 4 {
		return false
	}
	crc0 := str[len(str)-2:]
	str = str[0 : len(str)-3]
	crc := CRC([]byte(str))
	v := utils.HexToInt(crc0)
	return crc == byte(v)
}

func (this *NmeaDecoder) CacheBuf() []byte {
	return this.cache.Bytes()
}

func (this *NmeaDecoder) InputByte(v byte) int {
	if this.decodeState <= 0 {
		this.Reset()
	}

	this.cache.WriteByte(v)
	l := this.cache.Len()
	if l == 1 {
		if v != '$' {
			this.decodeState = -1
			return 0
		}
	} else if l <= 8 {
		if v == '$' && l > 1 { // $$GPGGA, $PXXXX$
			this.cache.Delete(0, l-1)
			return 0
		}
		if IsNmeaChr(v) {
			return 0
		}
		this.decodeState = -1
		return 0
	} else {
		if !IsNmeaChr(v) {
			this.decodeState = -1
			return 0
		}
		if this.starIdx > 0 {
			if this.starIdx+3 == this.cache.Len() { // 校验码
				this.checkRepair()
				this.decodeState = 0
				nmeaStr := this.cache.String()
				this.LastNmeaText = nmeaStr
				if this.OnNmea != nil {
					this.OnNmea(this, nmeaStr)
				}
				return 1
			}
		} else {
			if this.cache.Len() > 128 { // 超过128 还没有结束
				this.decodeState = -1
				return -1
			}
			if v == '*' {
				this.starIdx = this.cache.Len() - 1 // 星号的位置
			}
		}
	}
	return 0

}
